<?php

/**
 * 类名 Ssh2Sftp
 * 创建者: TonicGB
 * 说明:
 */
class Ssh2Sftp
{
    protected $postCharset="UTF-8";//表单提交字符集编码
    protected $fileCharset="UTF-8";//文件编码
    protected $uploadDir="/home/check/";//上传文件的根目录
    protected $downloadDir="/home/overcheck/"; //下载文件的根目录
    protected $localDir="/home/baobei/";
    protected $sftpHeader="ssh2.sftp://"; //ssh2 sftp连接头,使用ssh2里面的sftp读取存在的文件,以及创建文件

    protected $server;  //服务器
    protected $port;    //端口
    protected $userName;//用户名
    protected $password;//密码
    protected $resSFTP; //链接资源的句柄

    /**
     * Ssh2Sftp constructor.
     * 初始化参数
     * @param $server
     * @param $port
     * @param $userName
     * @param $password
     */
    public function __construct($server,$port,$userName,$password)
    {
        $this->server=$server;
        $this->port=$port;
        $this->userName=$userName;
        $this->password=$password;
        $this->resSFTP=$this->connect();
    }

    /**
     * 使用sftp协议方式登录链接ftp服务器
     * @return bool|resource
     */
    protected function connect()
    {
        //连接远程服务器获取链接
        $resConnection=ssh2_connect($this->server,$this->port,$this->userName,$this->password);
        //使用用户名和密码方式进行连接登录验证
        if (ssh2_auth_password($resConnection, $this->userName, $this->password)) {
            //初始化SFTP子系统  请求从一个已经连接子系统SFTP服务器SSH2安全性会更高
            return ssh2_sftp($resConnection);
        } else {
            return false;
        }


    }

    /**
     * 上传文件并写入数据
     * @param $filename 文件名
     * @param $content   数据
     */
    public function upload($filename, $content)
    {
        //上传文件路径
        $upfile=$this->uploadDir.pathinfo($filename,PATHINFO_BASENAME);
        //使用open 以写入方式打开 访问sftpurls.如果文件不存在则尝试创建
        $sftpStream=@fopen($this->sftpHeader . $this->resSFTP . $upfile,'w');
        try {
            if (!$sftpStream) {
                throw new Exception("Could not open remote file: $file");
            }
            //写入时设置数据字符编码避免乱码,设置flag加强控制转换
            $data_to_send=$this->strConvert($content,true);
            if ($data_to_send === false) {
                throw new Exception("Could not Convert Charset: $file.")
            }
            //向文件/资源写入文件
            if (@fwrite($sftpStream, $data_to_send) === false) {
                throw new Exception("Could not send data from file: $file.");
            }
            //关闭一个打开的文件/网络连接资源
            fclose($sftpStream);
        } catch (Exception $e) {
            echo'Exception: ' . $e->getMessage();
            fclose($sftpStream);//关闭资源
        }

    }

    /**
     * 获得远程ftp文件数据
     * @param $fileName 文件名
     * @return string
     */
    public function getdata($fileName)
    {
        $opts = array(
            'http' => array(
                'method' => 'GET',
                'timeout' => 60
            )
        );
        //创建并返回一个文本数据流.设置使用file_get_contents请求地址的请求方式和超时时间
        $context = stream_context_create($opts);
        $strData = file_get_contents($this->sftpHeader . $this->resSFTP . $this->downloadDir . $fileName, false, $context);
        //再将读取的数据转换成utf-8
        return $this->strConvert($strData, false);
    }

    public function downfile($fileName)
    {
        $localfile=$this->localDir.$fileName;
        //获取远程ftp数据
        $data=$this->getdata($fileName);
        //未获取到数据
        if (!$data) {
            echo "未取得ftp上面的数据";exit;
        }
        //向指定文件中写入数据
        if (!file_put_contents($localfile, $data)) {
            echo "写入失败,请检查时候权限问题";exit;
        }
        //header通知浏览器并下载到客户端
        header("Content-Type: application/force-download");//强行下载
        header("Content-Disposition: attachment; filename=".basename($local));//修改文件名
        readfile($local);//文件输出下载到客户端
        exit;
    }

    /**
     * 转换文件编码
     * @param $strText  字符串数据
     * @param bool $flag  flag标识加强控制编码转换
     * @return string
     */
    public function strConvert($strText, $flag = true)
    {
        //检测字符串编码  如果检测结果是EUC-CN在提供的检测编码数组中没有.不要惊讶EUC-CN是gb2312编码的一种表示方法
        $encode = mb_detect_encoding($strText, array('UTF-8', 'GB2312', 'GBK'));
        //如果是UTF-8 为了避免写入文件时和文件编码不对导致乱码需要转变gb2312. 可以使用GBK,GBK在原来基础上增加一些汉字，这里使用GB18030,因为他在GBK的基础上又增加了一部分汉字.
        if ($encode == "UTF-8" && $flag === true) {
            return @iconv('UTF-8', 'GB18030', $strText);
        }
        if ($encode == "EUC-CN" && $flag === false) {
            return @iconv('GB18030', 'UTF-8', $strText);
        }

        return $strText;
    }


}

